import React from "react";
import { Field } from "@formily/core";
import { ISchema } from "@formily/react";
import { IFormCollapse } from "@formily/antd";
import { getOptions } from "src/utils";
import { Typography, Button } from "antd";

interface Props {
  schemaType: string;
  storageUri?: string;
  entityName?: string;
  idc: string[];
  formCollapse: IFormCollapse;
  setVisible: (visible: boolean) => void;
}

const useSchema = (props: Props) => {
  const entityNameFnSchema = (schemaType: string): ISchema => {
    const componentProps =
      schemaType === "edit"
        ? { disabled: true, default: props.entityName }
        : {};
    return {
      type: "string",
      title: "Name",
      required: true,
      "x-decorator": "FormItem",
      "x-component": "Input",
      "x-component-props": {
        addonBefore: `${props.storageUri?.split("-")[0]}-`,
        ...componentProps,
      },
    };
  };

  const descriptionFnSchema = (required: boolean): ISchema => ({
    type: "string",
    title: "Description",
    required,
    "x-decorator": "FormItem",
    "x-component": "Input",
  });

  const storageUriFnSchema = (schemaType: string): ISchema => {
    const componentProps = schemaType === "edit" ? {} : { disabled: true };
    return {
      type: "string",
      title: "Storage Uri",
      required: true,
      default: props.storageUri,
      "x-decorator": "FormItem",
      "x-component": "FetchSelect",
      "x-component-props": componentProps,
    };
  };

  const typeSchema: ISchema = {
    type: "string",
    title: "Field Type",
    required: true,
    "x-decorator": "FormItem",
    "x-component": "Select",
    "x-reactions": (field: Field) => {
      // 控制 codec 的显隐
      field.form.setFieldState(field.query(".codec"), (state) => {
        state.display =
          field.value === "list" || field.value === "struct"
            ? "visible"
            : "none";
      });
      // 控制 enum 的显隐
      field.form.setFieldState(field.query(".enum"), (state) => {
        state.display = field.value === "enum" ? "visible" : "none";
      });
      // 控制 itemType 的显隐
      field.form.setFieldState(field.query(".itemType"), (state) => {
        state.display = field.value === "list" ? "visible" : "none";
      });
      // 控制 columns 中 columnType 的值
      field.form.setFieldState(field.query("..columns.columnType"), (state) => {
        const map = {
          string: "VARCHAR",
          boolean: "TINYINT",
          float32: "FLOAT",
          float64: "DOUBLE",
          "time.Time": "TIMESTAMP",
          list: "JSON",
          struct: "JSON",
          enum: "TINYINT",
          uint8: "SMALLINT",
          uint16: "MEDIUMINT",
          uint32: "INT",
          uint64: "BIGINT",
          int8: "SMALLINT",
          int16: "MEDIUMINT",
          int32: "INT",
          int64: "BIGINT",
        };
        // @ts-ignore
        state.value = map[field.value];
      });
    },
    enum: getOptions([
      "string",
      "boolean",
      "float32",
      "float64",
      "time.Time",
      "list",
      "struct",
      "enum",
      "uint8",
      "uint16",
      "uint32",
      "uint64",
      "int8",
      "int16",
      "int32",
      "int64",
    ]),
  };

  const enumSchema: ISchema = {
    type: "array",
    title: "Enum",
    required: true,
    "x-decorator": "FormItem",
    "x-component": "ArrayItems",
    items: {
      type: "object",
      properties: {
        space: {
          type: "void",
          "x-component": "Space",
          properties: {
            index: {
              type: "string",
              title: "Index",
              required: true,
              "x-decorator": "FormItem",
              "x-component": "Input",
              "x-reactions": (field: Field) => {
                const path = field.path.entire.toString().split(".");
                const index = path[path.length - 2];
                !field.value && (field.value = index);
              },
            },
            value: {
              type: "string",
              title: "Value",
              required: true,
              "x-decorator": "FormItem",
              "x-component": "Input",
            },
            remove: {
              type: "void",
              "x-decorator": "FormItem",
              "x-component": "ArrayItems.Remove",
            },
          },
        },
      },
    },
    properties: {
      add: {
        type: "void",
        title: "Add Enum Value",
        "x-component": "ArrayItems.Addition",
      },
    },
  };

  const columnTypeSchema: ISchema = {
    type: "string",
    title: "Column Type",
    required: true,
    "x-decorator": "FormItem",
    "x-component": "AntdSelect",
    "x-reactions": (field: Field) => {
      const map = {
        string: ["VARCHAR", "CHAR", "BLOB", "TEXT"],
        boolean: ["TINYINT"],
        float32: ["FLOAT"],
        float64: ["DOUBLE"],
        "time.Time": ["TIMESTAMP", "DATETIME"],
        list: ["JSON"],
        struct: ["JSON"],
        enum: ["ENUM", "TINYINT", "SMALLINT", "MEDIUMINT", "INT", "BIGINT"],
        uint8: ["SMALLINT"],
        uint16: ["MEDIUMINT"],
        uint32: ["INT"],
        uint64: ["BIGINT"],
        int8: ["SMALLINT"],
        int16: ["MEDIUMINT"],
        int32: ["INT"],
        int64: ["BIGINT"],
      };

      const path = field.path.entire.toString().split(".");
      const index = path[path.length - 3];
      const type = field.query(`fieldsAndColumns.${index}.fields.type`).value();

      // @ts-ignore
      type && field.setComponentProps({ options: getOptions(map[type]) });
    },
    "x-component-props": {
      options: getOptions([
        "VARCHAR",
        "CHAR",
        "BLOB",
        "TEXT",
        "FLOAT",
        "DOUBLE",
        "TIMESTAMP",
        "DATETIME",
        "JSON",
        "ENUM",
        "TINYINT",
        "SMALLINT",
        "MEDIUMINT",
        "INT",
        "BIGINT",
      ]),
    },
  };

  const schema: ISchema = {
    type: "object",
    properties: {
      div: {
        type: "void",
        "x-component": "FormCollapse",
        "x-component-props": {
          formCollapse: props.formCollapse,
          style: { display: "flex", flexDirection: "column" },
        },
        properties: {
          collapsePanel1: {
            type: "void",
            "x-component": "FormCollapse.CollapsePanel",
            "x-component-props": {
              header: <Typography.Title level={5}>Base Info</Typography.Title>,
            },
            properties: {
              baseInfo: {
                type: "object",
                "x-component": "Div",
                "x-component-props": {
                  style: { display: "flex" },
                },
                properties: {
                  entity: {
                    type: "void",
                    "x-component": "Div",
                    "x-component-props": {
                      style: { flex: 1 },
                    },
                    properties: {
                      entityName: entityNameFnSchema(props.schemaType),
                      description: descriptionFnSchema(true),
                      owners: {
                        type: "array",
                        title: "Owners",
                        required: true,
                        "x-decorator": "FormItem",
                        "x-component": "OwnersSelect",
                      },
                    },
                  },
                  mapping: {
                    type: "void",
                    "x-component": "Div",
                    "x-component-props": {
                      style: { flex: 1 },
                    },
                    properties: {
                      storageUri: storageUriFnSchema(props.schemaType),
                      tableName: {
                        type: "string",
                        title: "Table Name",
                        required: true,
                        "x-decorator": "FormItem",
                        "x-component": "Input",
                      },
                      idcs: {
                        type: "array",
                        title: "Idcs",
                        required: true,
                        "x-decorator": "FormItem",
                        "x-component": "Select",
                        "x-component-props": {
                          mode: "multiple",
                        },
                        enum: getOptions(props.idc),
                      },
                    },
                  },
                },
              },
            },
          },
          collapsePanel2: {
            type: "void",
            "x-component": "FormCollapse.CollapsePanel",
            "x-component-props": {
              header: (
                <div style={{ display: "flex" }}>
                  <Typography.Title level={5}>
                    Fields & Columns
                  </Typography.Title>
                  <Button
                    type="primary"
                    style={{ marginLeft: 10 }}
                    onClick={() => props.setVisible(true)}
                  >
                    Import SQL
                  </Button>
                </div>
              ),
            },
            properties: {
              fieldsAndColumns: {
                type: "array",
                "x-component": "ArrayCards",
                "x-component-props": {
                  title: (
                    <>
                      <span style={{ margin: "0 48% 0 3%" }}>Field</span>
                      Column
                    </>
                  ),
                },
                items: {
                  type: "object",
                  "x-component": "Div",
                  "x-component-props": {
                    style: { display: "flex" },
                  },
                  properties: {
                    index: {
                      type: "void",
                      "x-component": "ArrayCards.Index",
                    },
                    fields: {
                      type: "object",
                      "x-component": "Div",
                      "x-component-props": {
                        style: { flex: 1 },
                      },
                      properties: {
                        name: {
                          type: "string",
                          title: "Field Name",
                          required: true,
                          "x-decorator": "FormItem",
                          "x-component": "Input",
                          "x-reactions": (field: Field) => {
                            // 控制 columns 中 columnName、FieldName 的值
                            const path = field.path.entire
                              .toString()
                              .split(".");
                            const index = path[path.length - 3];
                            const target = `fieldsAndColumns.${index}.columns`;

                            field.form.setFieldState(
                              `*(${target}.columnName, ${target}.fieldName)`,
                              (state) => {
                                state.value = field.value;
                              }
                            );
                          },
                        },
                        description: descriptionFnSchema(false),
                        type: typeSchema,
                        codec: {
                          type: "string",
                          title: "Codec",
                          required: true,
                          default: "json",
                          "x-decorator": "FormItem",
                          "x-component": "Radio.Group",
                          enum: getOptions(["json"]),
                        },
                        enum: enumSchema,
                        itemType: {
                          type: "string",
                          title: "Field Item Type",
                          required: true,
                          "x-decorator": "FormItem",
                          "x-component": "Select",
                          enum: getOptions([
                            "string",
                            "boolean",
                            "list",
                            "struct",
                          ]),
                        },
                        itemType2: {
                          type: "string",
                          title: "Field Item Type2",
                          required: true,
                          "x-decorator": "FormItem",
                          "x-component": "Select",
                          "x-reactions": (field: Field) => {
                            field.form.setFieldState(
                              field.query(".itemType"),
                              (state) => {
                                field.display =
                                  state.value === "list" ? "visible" : "none";
                              }
                            );
                          },
                          enum: getOptions(["string", "boolean", "struct"]),
                        },
                        innerFields: {
                          type: "array",
                          title: "InnerFields",
                          required: true,
                          "x-decorator": "FormItem",
                          "x-component": "OpenInnerFieldsModalButton",
                          "x-reactions": (field: Field) => {
                            // 控制自身的显隐
                            const path = field.path.entire
                              .toString()
                              .split(".");
                            const index = path[path.length - 3];
                            const target = `fieldsAndColumns.${index}.fields`;

                            const type = field.query(`${target}.type`).value();

                            const itemType = field
                              .query(`${target}.itemType`)
                              .value();

                            const itemType2 = field
                              .query(`${target}.itemType2`)
                              .value();

                            field.display =
                              type === "struct" ||
                              itemType === "struct" ||
                              itemType2 === "struct"
                                ? "visible"
                                : "none";

                            // 将该 field 的值传进去
                            const fieldData = field
                              .query(path.slice(0, path.length - 1).join("."))
                              .value();
                            field.setComponentProps({ fieldData });
                          },
                        },
                      },
                    },
                    columns: {
                      type: "object",
                      "x-component": "Div",
                      "x-component-props": {
                        style: { flex: 1 },
                      },
                      properties: {
                        columnName: {
                          type: "string",
                          title: "Column Name",
                          required: true,
                          "x-decorator": "FormItem",
                          "x-component": "Input",
                        },
                        fieldName: {
                          type: "string",
                          title: "Field Name",
                          required: true,
                          "x-decorator": "FormItem",
                          "x-component": "Input",
                          "x-component-props": {
                            disabled: true,
                          },
                        },
                        columnType: columnTypeSchema,
                      },
                    },
                    remove: {
                      type: "void",
                      "x-component": "ArrayCards.Remove",
                      "x-component-props": {
                        style: { color: "red", marginRight: 20 },
                      },
                    },
                    moveUp: {
                      type: "void",
                      "x-component": "ArrayCards.MoveUp",
                    },
                    moveDown: {
                      type: "void",
                      "x-component": "ArrayCards.MoveDown",
                    },
                  },
                },
                properties: {
                  add: {
                    type: "void",
                    title: "Add Field & Column",
                    "x-component": "ArrayCards.Addition",
                  },
                },
              },
            },
          },
          collapsePanel3: {
            type: "void",
            "x-component": "FormCollapse.CollapsePanel",
            "x-component-props": {
              header: <Typography.Title level={5}>Indexs</Typography.Title>,
            },
            properties: {
              indexs: {
                type: "array",
                "x-component": "ArrayCards",
                "x-component-props": {
                  title: "Field Index",
                  style: { width: "50%" },
                },
                items: {
                  type: "object",
                  "x-component": "Div",
                  "x-component-props": {
                    style: { display: "flex" },
                  },
                  properties: {
                    index: {
                      type: "void",
                      "x-component": "ArrayCards.Index",
                    },
                    div: {
                      type: "void",
                      "x-component": "Div",
                      "x-component-props": {
                        style: { flex: 1 },
                      },
                      properties: {
                        fieldGroup: {
                          type: "string",
                          title: "Field Group",
                          required: true,
                          "x-decorator": "FormItem",
                          "x-component": "AntdSelect",
                          "x-component-props": { mode: "multiple" },
                          "x-reactions": (field: Field) => {
                            // 自身的 options 受控与 FieldName
                            const fieldNames = field.query(
                              "fieldsAndColumns.*.fields.name"
                            );
                            // @ts-ignore
                            const length = fieldNames.addresses.length;

                            const values: string[] = [];
                            for (let i = 0; i < length; i++) {
                              values[i] = field
                                .query(`fieldsAndColumns.${i}.fields.name`)
                                .value();
                            }
                            field.setComponentProps({
                              options: getOptions(values),
                            });

                            // 自身存在值非 FieldName 时，报错
                            if (!field.value) return;
                            let flag = true;
                            for (let i = 0; i < field.value.length; i++) {
                              if (values.indexOf(field.value[i]) === -1) {
                                flag = false;
                                break;
                              }
                            }
                            // @ts-ignore
                            field.selfErrors = flag
                              ? ""
                              : "field Group中的值必须源于field Name";
                          },
                        },
                        primary: {
                          type: "boolean",
                          title: "Primary Key",
                          required: true,
                          default: false,
                          "x-decorator": "FormItem",
                          "x-component": "Radio.Group",
                          enum: getOptions([
                            ["true", true],
                            ["false", false],
                          ]),
                          "x-reactions": (field: Field) => {
                            // indexs 下的 primary 仅有一个可以为 true
                            const primaryKeys = field.query("indexs.*.primary");
                            // @ts-ignore
                            const length = primaryKeys.addresses.length;

                            let count = 0;
                            for (let i = 0; i < length; i++) {
                              if (field.query(`indexs.${i}.primary`).value()) {
                                count++;
                              }
                            }
                            // @ts-ignore
                            field.selfErrors =
                              count === 1 || field.value === undefined
                                ? ""
                                : "Indexs中的Primary Key有且仅有一个可以为true";

                            // primary 为 true 时，unique 的值也为 true
                            if (field.value) {
                              field.form.setFieldState(
                                field.query(".unique"),
                                (state) => {
                                  state.value = true;
                                }
                              );
                            }
                          },
                        },
                        unique: {
                          type: "string",
                          title: "Unique Key",
                          required: true,
                          default: false,
                          "x-decorator": "FormItem",
                          "x-component": "Radio.Group",
                          enum: getOptions([
                            ["true", true],
                            ["false", false],
                          ]),
                        },
                      },
                    },
                    remove: {
                      type: "void",
                      "x-component": "ArrayCards.Remove",
                      "x-component-props": {
                        style: { color: "red", marginRight: 20 },
                      },
                    },
                    moveUp: {
                      type: "void",
                      "x-component": "ArrayCards.MoveUp",
                    },
                    moveDown: {
                      type: "void",
                      "x-component": "ArrayCards.MoveDown",
                    },
                  },
                },
                properties: {
                  add: {
                    type: "void",
                    title: "Add Field Index",
                    "x-component": "ArrayCards.Addition",
                    "x-component-props": {
                      style: { width: "50%" },
                    },
                  },
                },
              },
            },
          },
        },
      },
    },
  };

  return schema;
};

export default useSchema;
